﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Runtime.Serialization;

namespace CGOnline.Server.Core
{
    [DataContract(Namespace="CGOline.Server.Core.StateObject")]
    public class StateObject:ServerObject,IState
    {
        [DataMember]
        private Dictionary<string, List<string>> _dict;
        [DataMember]
        private Dictionary<string, string> _currectstates;

        public StateObject()
        {
            //initialize state metadata
            _dict = new Dictionary<string, List<string>>();
            var attributes= this.GetType().GetCustomAttributes(typeof(StateAnnouncementAttribute),true) as StateAnnouncementAttribute[];
            foreach (var attribute in attributes)
            {
                if (!_dict.ContainsKey(attribute.StateGroup))
                    _dict.Add(attribute.StateGroup, new List<string>());
                _dict[attribute.StateGroup].Add(attribute.StateName);
            }

            //initialize states
            _currectstates = new Dictionary<string, string>();
            foreach (string key in _dict.Keys)
            {
                _currectstates.Add(key, _dict[key][0]);
            }
        }

        //return states enum
        public Dictionary<string, List<string>> ListStateEnum()
        {
            var ret= new Dictionary<string, List<string>>();
            foreach(var pair in _dict)
            {
                var pairvalues=new List<string>();
                foreach(var pairvalue in pair.Value)
                    pairvalues.Add(pairvalue);
                ret.Add(pair.Key,pairvalues);
            }
            return ret;

        }

        //return current states dictionary
        public Dictionary<string, string> ListCurrentState()
        {
            var ret = new Dictionary<string, string>();
            foreach (var pair in _currectstates)
                ret.Add(pair.Key, pair.Value);
            return ret;
        }

        //return current state of stategroup
        public string GetState(string stateGroup)
        {
            if (!_dict.ContainsKey(stateGroup))
                throw new StateException(string.Format("StateGroup:{0} not exists.",stateGroup));
                //return null;
            return _currectstates[stateGroup];
        }

        public bool GoToState(string stateGroup, string state)
        {
            if (!_dict.ContainsKey(stateGroup))
                throw new StateException(string.Format("StateGroup:{0} not exists.",stateGroup));
            if(!_dict[stateGroup].Exists(st=>st==state))
                throw new StateException(string.Format("State:{0} not exists.", state));
            if (_currectstates[stateGroup] == state)
                return false;
            //trigger the event
            OnStateChange(stateGroup, _currectstates[stateGroup], state);
            _currectstates[stateGroup] = state;
            return true;
        }

        private void OnStateChange(string stategroup,string oldstate,string newstate)
        {
            if (StateChanged != null)
                StateChanged(this, new StateEventArgs
                {
                    StateGroup = stategroup,
                    OriginState = oldstate,
                    NewState = newstate
                });
        }

        public event EventHandler<StateEventArgs> StateChanged;

    }
}
